package com.ruoyi.service.impl;

import cn.hutool.core.util.IdUtil;
import com.ruoyi.common.redis.service.RedisService;
import com.ruoyi.config.DelayedQueueConfig;
import com.ruoyi.domain.BmInordergoodslist;
import com.ruoyi.domain.BmInorderlist;
import com.ruoyi.mapper.OrderMapper;
import com.ruoyi.member.api.RemoteSellerMyOrderService;
import com.ruoyi.service.OrderService;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @Author: star
 * @Description:
 * @DateTime: 2023/8/11 21:25
 **/
@Service
public class OrderServiceImpl implements OrderService {
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private RedissonClient redissonClient;
    @Autowired
    private RemoteSellerMyOrderService remoteSellerMyOrderService;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private RedisService redisService;

    @Override
    public List<Map<String, Object>> getShoppingList(Integer goodsId, Integer id) {
        List<Map<String, Object>> shoppingList = orderMapper.getShoppingSpecification(id);
        List<Map<String, Object>> shoppingGoods = orderMapper.getShoppingGoods(goodsId);
        for (Map<String, Object> map : shoppingGoods) {
            for (int i = 0; i < map.size(); i++) {
                shoppingList.get(0).put("goods_name", map.get("goods_name"));
                shoppingList.get(0).put("mechanism_code", map.get("mechanism_code"));
                shoppingList.get(0).put("mechanism_name", map.get("mechanism_name"));
            }
        }
        return shoppingList;
    }

    @Override
    @Transactional
    public boolean payOrder(Map<String,Object> map) {
        boolean payResult = false;
        RLock locks = redissonClient.getLock("locks");
        try{
            boolean b = locks.tryLock(100, 30, TimeUnit.SECONDS);
            if (b){
                Integer sellerId = Integer.parseInt(map.get("sellerId").toString());
                Double amount = Double.parseDouble(map.get("amount").toString());
                String orderCode = map.get("orderCode").toString();
                String warehouseCode = map.get("warehouseCode").toString();
                Integer payType = Integer.parseInt(map.get("payType").toString());
                Double money = orderMapper.getAmount(sellerId);
//               当支付方式为0(余额支付) 且 余额足够的情况下，修改余额：之前余额-当前订单总价
                if (payType == 0){
                    if (money >= amount){
                        amount = money - amount;
                        boolean amountResult = orderMapper.updateAmount(sellerId,amount);
                        if (amountResult){
                            Map<String,Object> sellerMap = orderMapper.getSellerAllMessage(sellerId);
                            redisService.setCacheObject("login:"+sellerId,sellerMap);
                        }else {
                            throw new RuntimeException("余额不足！");
                        }
                    }
                }
//          创建订单主表对象
                BmInorderlist bl = new BmInorderlist();
//          订单编号
                bl.setOrderCode(orderCode);
//          支付时间
                LocalDateTime now = LocalDateTime.now();
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                String formattedDate = now.format(formatter);
                bl.setPayTime(formattedDate);
//          调度，给出仓库管理人员id和物流人员id
                com.ruoyi.member.api.domain.BmInorderlist reBl = new com.ruoyi.member.api.domain.BmInorderlist();
                reBl.setOrderCode(orderCode);
                reBl.setWarehouseCode(warehouseCode);
                remoteSellerMyOrderService.one(reBl);
                if (payType == 0 ){
                    payResult = orderMapper.payOrderType0(bl);
                }else if (payType == 3){
                    payResult = orderMapper.payOrderType3(bl);
                }
            }
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } finally {
            locks.unlock();
        }
        return payResult;
    }

    @Override
    public boolean password(Map<String, Object> map) {
//        拿到id去获取该商户的密码
        Integer id = (Integer) map.get("id");
        String encodePassword = orderMapper.getPassword(id);
//        把前端传过来的原始密码 进行比对
        String password = (String) map.get("password");
        boolean result = passwordEncoder.matches(password, encodePassword);
        return result;
    }

    @Override
    public Map<String, Object> test(Integer id) {
        return orderMapper.getSellerAllMessage(id);
    }

    @Override
    @Transactional
    public String addOrder(Map<String,Object> map,List<Map<String,Object>> goods) {
//        分布式锁,使用RedissonClient声明一个锁
        RLock lock = redissonClient.getLock("lock");
        boolean addHead = false;
        boolean ifStock = true;
        boolean addItems = false;
        String orderCode = null;
        try {
//            参数1.加锁的等待时间
//            参数2.加锁以后30秒以后释放锁
//            参数3.返回值 true加锁成功，false加锁失败
            boolean b = lock.tryLock(100, 30, TimeUnit.SECONDS);
            if (b) {
                    System.out.println("加锁，查询数据库...");
                //        订单主表创建订单时数据
                BmInorderlist bl = new BmInorderlist();
//        获取生成的uuid
                orderCode = IdUtil.simpleUUID();
                bl.setOrderCode(orderCode);
                bl.setOrderStep(1);
//                获取指定的时间格式的当前日期
                LocalDateTime now = LocalDateTime.now();
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                String formattedDate = now.format(formatter);
                bl.setCreateTime(formattedDate);

                bl.setOrderState(1);
                bl.setSellerId(Long.parseLong(map.get("sellerId").toString()));
                bl.setDeliveryFee(Double.parseDouble(map.get("deliveryFee").toString()));
                bl.setAmount(Double.parseDouble(map.get("amount").toString()));
                bl.setMark(map.get("mark").toString());
                bl.setWarehouseCode(map.get("warehouseCode").toString());
                bl.setAddress(map.get("address").toString());
//        如果账户余额>订单所需费用 创建订单主表
                Double amount = orderMapper.getAmount(Integer.parseInt(map.get("sellerId").toString()));
                if (amount >= Double.parseDouble(map.get("amount").toString())){
                    addHead = orderMapper.addHead(bl);
                }else {
                    throw new RuntimeException("余额不足订单创建失败！");
                }

//        订单明细表创建订单时的数据
                List<BmInordergoodslist> list = new ArrayList<>();
                for (int i = 0; i < goods.size(); i++) {
                    BmInordergoodslist bgl = new BmInordergoodslist();
                    bgl.setOrderCode(orderCode);
                    bgl.setGoodsId(Long.parseLong(goods.get(i).get("goodsId").toString()));
                    bgl.setSpecificationId(Long.parseLong(goods.get(i).get("specificationId").toString()));
                    bgl.setSpecificationName(goods.get(i).get("specificationName").toString());
                    bgl.setGoodsName(goods.get(i).get("goodsName").toString());
                    bgl.setGoodsImg(goods.get(i).get("goodsImgUrl").toString());
                    bgl.setBuyNum(Long.parseLong(goods.get(i).get("buyNum").toString()));
                    Double price = Double.parseDouble(goods.get(i).get("buyNum").toString()) * Double.parseDouble(goods.get(i).get("oldPrice").toString());
                    bgl.setPrice(price);
//            判断商品库存 >= 购买的数量 依次创建订单明细表
                    Integer num = orderMapper.getGoodsStock(Integer.parseInt(goods.get(i).get("specificationId").toString()));
                    if (num >= Integer.parseInt(goods.get(i).get("buyNum").toString())){
                        list.add(bgl);
                        Integer newNum = num - Integer.parseInt(goods.get(i).get("buyNum").toString());
                        orderMapper.updateStock(Integer.parseInt(goods.get(i).get("specificationId").toString()),newNum);
                    }else {
                        ifStock = false;
                    }
                }
                if (ifStock){
                    addItems = orderMapper.addItem(list);
                }else {
                    throw new RuntimeException("存在商品库存不足");
                }
                if (addHead && addItems){
                    //放到消息队列 bl
                    rabbitTemplate.convertAndSend(DelayedQueueConfig.DELAYED_EXCHANGE_NAME, DelayedQueueConfig.DELAYED_ROUTING_KEY, orderCode, msg -> {
                        msg.getMessageProperties().setDelay(60000);//1分钟
                        return msg;
                    });
                }
            }
        }catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
//            手动释放锁
            lock.unlock();
        }
        return orderCode;
    }
}
